package com.geekhalo.info.domain.info.video;

import com.geekhalo.info.domain.category.InfoCategory;
import com.geekhalo.info.domain.category.exception.InfoCategoryNotFoundException;
import com.geekhalo.info.domain.info.BaseInfo;
import com.geekhalo.info.domain.info.video.create.CreateVideoInfoCommand;
import com.geekhalo.info.domain.info.video.create.CreateVideoInfoContext;
import com.geekhalo.info.domain.info.video.create.VideoInfoCreatedEvent;
import com.geekhalo.info.domain.info.video.offline.OfflineVideoInfoCommand;
import com.geekhalo.info.domain.info.video.offline.OfflineVideoInfoContext;
import com.geekhalo.info.domain.info.video.offline.VideoInfoOfflinedEvent;
import com.geekhalo.info.domain.info.video.online.OnlineVideoInfoCommand;
import com.geekhalo.info.domain.info.video.online.OnlineVideoInfoContext;
import com.geekhalo.info.domain.info.video.online.VideoInfoOnlinedEvent;
import com.geekhalo.info.domain.info.video.update.UpdateVideoInfoCommand;
import com.geekhalo.info.domain.info.video.update.UpdateVideoInfoContext;
import com.geekhalo.info.domain.info.video.update.VideoInfoUpdatedEvent;
import com.geekhalo.lego.core.command.support.AbstractAggRoot;
import lombok.AccessLevel;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.persistence.*;
import java.util.Optional;

@Entity
@Table(name = "video_info")
@PrimaryKeyJoinColumn(name = "info_id")
@Data
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Setter(AccessLevel.PRIVATE)
public class VideoInfo extends BaseInfo {

    private Long duration;

    private String videoUrl;

    public static VideoInfo create(CreateVideoInfoContext context) {
        CreateVideoInfoCommand command = context.getCommand();

        Optional<InfoCategory> categoryOpt = context.getCategory();
        if (!categoryOpt.isPresent()){
            throw new InfoCategoryNotFoundException();
        }
        InfoCategory infoCategory = categoryOpt.get();
        infoCategory.checkCanCreateInfo();

        VideoInfo videoInfo = new VideoInfo();
        videoInfo.setCategoryId(infoCategory.getId());
        videoInfo.setTitle(command.getTitle());
        videoInfo.setDuration(command.getDuration());
        videoInfo.setVideoUrl(command.getVideoUrl());
        videoInfo.init();
        return videoInfo;
    }

    private void init() {
        this.setOnline();
        this.addEvent(new VideoInfoCreatedEvent(this));
    }

    public void update(UpdateVideoInfoContext context) {
        UpdateVideoInfoCommand command = context.getCommand();
        setTitle(command.getTitle());
        setVideoUrl(command.getVideoUrl());
        setDuration(command.getDuration());

        addEvent(new VideoInfoUpdatedEvent(this));
    }

    public void offline(OfflineVideoInfoContext context) {
        if (this.setOffline()) {
            addEvent(new VideoInfoOfflinedEvent(this));
        }
    }

    public void online(OnlineVideoInfoContext context) {
        if (this.setOnline()) {
            addEvent(new VideoInfoOnlinedEvent(this));
        }
    }
}